#pragma once
#include <SDL/SDL.h>
#include "GlobalStructs.h"
#include "Tile.h"
//#include <string>
#include <list>
#include <map>
#include <utility>
#include <iostream>
using namespace std;

class Player
{
private:
	/*--- Non-Class Variables ---*/
	list<Tile> m_tilesList;
	Position m_playerLoc;
	/*--- Member Variables ---*/
	CoinSack m_goldOwned;
	int m_playerID;
	int m_turnsCompleted;
	Uint32 m_turnStart;
	Uint32 m_turnEnd;
	list<Uint32> m_timeTakenEachTurnList;
	list<BoolInt> m_actions; // if action was move or place a tile [0,1] and what tile it was
	//bool m_isDrakonSummoner;
	//int m_mindControlledCount;
	multimap<int,int> m_affectedBy; // player/tileFlag
public:
	/*--- Constructors ---*/
	Player():m_playerID(-1),m_playerLoc(Position(BOARD_START_X,BOARD_START_Y)),m_turnsCompleted(0){
	}
	Player(int a_playerID, Position a_position)
		:m_playerID(a_playerID),
		 m_playerLoc(a_position),
		 m_goldOwned(CoinSack()),m_turnsCompleted(0){
	}
	~Player() {}
	/*--- Game Functions ---*/
	void setStartTimer(){ m_turnStart= SDL_GetTicks();}
	void setEndTimer(){ 
		m_turnEnd= SDL_GetTicks();
		m_timeTakenEachTurnList.push_back(m_turnEnd - m_turnStart);
	}
	void addAction(bool hasPlacedATile, int tileflag){
		m_actions.push_back(make_pair(hasPlacedATile,tileflag));
	}
	list<BoolInt> getActionList(){return m_actions;}
	list<Uint32> getTimeList(){return m_timeTakenEachTurnList;}
	void update();
	/*--- Accessors ---*/
	// gets total value of coins
	void addAffectInfo(int owner,int tileFlag){
		 m_affectedBy.insert(pair<int, int>(owner, tileFlag));
	}
	multimap<int,int> getAffectedMap(){return m_affectedBy;}
	void incTurnsCompleted(){m_turnsCompleted++;}
	CoinSack& getCoinSack() { return m_goldOwned; }
	void setCoinSack(CoinSack sack){ m_goldOwned = sack;}
	list<Tile>& getHandList(void);
	// gets current tile Location
	Position getPosition() { return m_playerLoc; }
	void setID(int id) { m_playerID = id; }
	bool hasTiles(){return m_tilesList.size() > 0;}
	int getID() { return m_playerID; }
	void setHandList(list<Tile>&);
	//bool isDrakonSummoner(){return m_isDrakonSummoner;}
	//void setAsSummoner(){m_isDrakonSummoner = true;}
	void addATileToHand(Tile tile);
	string toString();
	void setPos(Position pos);
	bool movePlayer(arrowDirection dest);

	int getTileFlagMostMovedInto(){
		list<BoolInt>::iterator it = m_actions.begin();
		int flagBuckets[20];
	//	// setup the buckets
		while(it != m_actions.end()){
			if(it->first == false){
				flagBuckets[it->second]++;
			}
			it++;
		}
	//	// go thru each bucket and see which has the most
		int count = 0;
		int mostUsedFlag = -1;
		for(int i = 0; i < 20; i++){
			if(count < flagBuckets[i]){
				count = flagBuckets[i];
				mostUsedFlag = i;
			}
		}
		return mostUsedFlag;
	}
	int getTileFlagMostPlaced(){
		list<BoolInt>::iterator it = m_actions.begin();
		int flagBuckets[20];
		// setup the buckets
		while(it != m_actions.end()){
			if(it->first == true){
				flagBuckets[it->second]++;
			}
			it++;
		}
		// go thru each bucket and see which has the most
		int count = 0;
		int mostUsedFlag = -1;
		for(int i = 0; i < 20; i++){
			if(count < flagBuckets[i]){
				count = flagBuckets[i];
				mostUsedFlag = i;
			}
		}
		return mostUsedFlag;
	}
	int gettimespickedon(){
		int times = 0;
		if(m_affectedBy.size() > 0){
			multimap<int,int>::iterator it = m_affectedBy.begin();
			
			// flag, flag
			for(;it != m_affectedBy.end();it++){
				if(it->first != m_playerID){
					switch(it->second){
						case ROTATE_TILE:
						case LOSE_A_COIN:
						case STEAL_GOLD_CCW:
						case STEAL_GOLD_CW:
						case MIND_CONTROL:
						// magical harp not added yet
						case MAP_TILE:
						case MOVE_DRAKON:
						//// strong wind not added yet
							times++;
							break;
					}
				}

			}
		}
		return times;
	}
	IntInt getMostPickedOnBy(){
		IntInt timesPickedon;
		int times = 0;
		int bullies[NUMBER_OF_PLAYERS];
		int meanestPlayer = -1;
		int meanCounter = 0;
		if(m_affectedBy.size() > 0){
			multimap<int,int>::iterator it = m_affectedBy.begin();
			// flag, flag
			for(;it != m_affectedBy.end();it++){
				if(it->first != m_playerID){
					switch(it->second){
						case ROTATE_TILE:
						case LOSE_A_COIN:
						case STEAL_GOLD_CCW:
						case STEAL_GOLD_CW:
						case MIND_CONTROL:
						// MAGICAL HARP not added yet
						case MAP_TILE:
						case MOVE_DRAKON:
						// STRONG WIND not added yet
							bullies[it->first]++;
							times++;
							break;
					}
				}
			}
			for(int i = 0; i < NUMBER_OF_PLAYERS; i++){
				if(meanCounter < bullies[i]){
					meanCounter = bullies[i]+1;
					meanestPlayer = i;
				}
			}
			timesPickedon = make_pair(meanestPlayer,meanCounter);
		}
		return timesPickedon;
	}
};